using System;
using System.Collections.Generic;
using System.Text;
using MediaPortal.GUI.Library;

namespace MyEmulators2
{
    public class Game : DBItem, DBInterface
    {
        public Game()
        {

        }

        public Game(String path, Emulator parentEmu)
        {
            Path = path == null ? "" : path;
            String x = path.Remove(path.LastIndexOf("."));
            Title = x.Substring(x.LastIndexOf("\\") + 1);
            parentEmulator = parentEmu;
            Visible = true;
            LaunchFile = "";
        }

        private int gameid = -2;
        public int GameID
        {
            get { return gameid; }
            set { gameid = value; }
        }

        private String title = "";
        public String Title
        {
            get { return title; }
            set { title = value; }
        }

        private String path = "";
        public String Path
        {
            get { return path; }
            set 
            { 
                path = value;

                String x = path.Remove(path.LastIndexOf("."));
                Filename = x.Substring(x.LastIndexOf("\\") + 1);
            }
        }

        private String filename = "";
        public String Filename
        {
            get { return filename; }
            set { filename = value; }
        }

        private Emulator parentEmulator = null;
        public Emulator ParentEmulator
        {
            get { return parentEmulator; }
            set { parentEmulator = value; }
        }

        private int grade = 0;
        public int Grade
        {
            get { return grade; }
            set { grade = value; }
        }

        private int playcount = 0;
        public int Playcount
        {
            get { return playcount; }
            set { playcount = value; }
        }

        private int yearmade = 0;
        public int Yearmade
        {
            get { return yearmade; }
            set { yearmade = value; }
        }

        private DateTime latestplay = DateTime.MinValue;
        public DateTime Latestplay
        {
            get { return latestplay; }
            set { latestplay = value; }
        }

        private String description = "";
        public String Description
        {
            get { return description; }
            set { description = value; }
        }

        private String genre = "";
        public String Genre
        {
            get { return genre; }
            set { genre = value; }
        }

        private String company = "";
        public String Company
        {
            get { return company; }
            set { company = value; }
        }

        private bool visible = true;
        public bool Visible
        {
            get { return visible; }
            set { visible = value; }
        }

        private bool favourite = false;
        public bool Favourite
        {
            get { return favourite; }
            set { favourite = value; }
        }
 
        public override string ToString()
        {
            return Title;
        }

        private String launchFile = "";
        public String LaunchFile
        {
            get { return launchFile; }
            set { launchFile = value; }
        }

        bool isInfoChecked = false;
        public bool IsInfoChecked
        {
            get { return isInfoChecked; }
            set { isInfoChecked = value; }
        }

        private String hash = "";
        public String Hash
        {
            get { return hash; }
            set { hash = value; }
        }

        public override ExtendedGUIListItem CreateGUIListItem()
        {
            ExtendedGUIListItem listItem = new ExtendedGUIListItem(title);
            listItem.AssociatedGame = this;

            using (ThumbGroup thumbs = new ThumbGroup(this))
                listItem.ThumbnailImage = thumbs.FrontCoverDefaultPath;

            return listItem;
        }

        public override void SetGUIProperties()
        {
            SetGUIProperties(false);
        }

        public void SetGUIProperties(bool isViews)
        {
            GUIPropertyManager.SetProperty("#item_title", this.Title);

            if (!isViews)
                GUIPropertyManager.SetProperty("#coverflow_label", this.ParentEmulator.ToString());
            GUIPropertyManager.SetProperty("#emulator_title", this.ParentEmulator.ToString());
            GUIPropertyManager.SetProperty("#game_grade", this.Grade.ToString());

            if (this.Description.Length > 0)
            {
                GUIPropertyManager.SetProperty("#game_description", this.Description);
            }
            else
            {
                GUIPropertyManager.SetProperty("#game_description", "");
            }

            if (this.Yearmade > 0)
                GUIPropertyManager.SetProperty("#game_yearmade", "" + this.Yearmade);
            else
                GUIPropertyManager.SetProperty("#game_yearmade", "");

            GUIPropertyManager.SetProperty("#game_genre", this.Genre);
            GUIPropertyManager.SetProperty("#game_company", this.Company);

            if (this.Latestplay.Year > 2000)
                GUIPropertyManager.SetProperty("#game_latestplay", (this.Latestplay.CompareTo(DateTime.MinValue) == 0) ? Translator.getString(TranslatorString.never) : this.Latestplay.ToShortDateString());
            else
                GUIPropertyManager.SetProperty("#game_latestplay", "");

            if (this.Playcount > 0)
                GUIPropertyManager.SetProperty("#game_playcount", "" + this.Playcount);
            else
                GUIPropertyManager.SetProperty("#game_playcount", "");
        }

        public Game Clone()
        {
            Game newGame = new Game(path, parentEmulator);

            newGame.GameID = this.gameid;
            newGame.Title = this.title;
            //newGame.Path = this.path;
            newGame.Filename = this.filename;
            newGame.Grade = this.grade;
            newGame.Playcount = this.playcount;
            newGame.Yearmade = this.yearmade;
            newGame.Latestplay = this.latestplay;
            newGame.Description = this.description;
            newGame.Genre = this.genre;
            newGame.Company = this.company;
            newGame.Visible = this.visible;
            newGame.Favourite = this.favourite;
            newGame.LaunchFile = this.launchFile;
            newGame.Hash = this.hash;

            return newGame;
        }

        int selectedProfile = -1;
        public int SelectedProfile 
        {
            get { return selectedProfile; }
            set { selectedProfile = value; } 
        }

        public EmulatorProfile GetSelectedProfile()
        {
            if (selectedProfile < 0)
            {
                return new EmulatorProfile(parentEmulator, false);
            }

            return DB.Instance.GetProfile(selectedProfile, parentEmulator);
        }

        public bool IsGoodmerge
        {
            get
            {
                if (string.IsNullOrEmpty(path))
                    return false;

                int index = path.LastIndexOf('.');
                if (index < 0)
                    return false; //file doesn't have an extension

                //get file extension
                string extension = path.Substring(index, path.Length - index).ToLower();
                //get configured Goodmerge extensions
                string[] goodmergeExts = Options.Instance.GetStringOption("goodmergefilters").Split(';');
                for (int x = 0; x < goodmergeExts.Length; x++)
                {
                    //see if extension matches filter
                    if (goodmergeExts[x].ToLower().EndsWith(extension))
                        return true;
                }
                //no match was found
                return false;
            }
        }

        #region DBInterface Members
        
        public const string TABLE_NAME = "Games";

        const string TABLE_STRING =
            "gameid INTEGER PRIMARY KEY AUTOINCREMENT, " +
            "path varchar(200), " +
            "parentemu int, " +
            "title varchar(100), " +
            "grade int, " +
            "playcount int, " +
            "yearmade int, " +
            "latestplay varchar(16), " +
            "description varchar(200), " +
            "genre varchar(50), " +
            "company varchar(50), " +
            "visible char(5), " +
            "favourite char(5), " +
            "LaunchFile varchar(200), " +
            "emuprofile int, " +
            "infochecked char(5), " +
            "hash varchar(100)";

        const string INSERT_STRING =
            "NULL, " +
            "'{0}', " + //encode(path)
            "{1}, " + //parentEmu UID
            "'{2}', " + //encode(title)
            "{3}, " + //grade
            "{4}, " + //playcount
            "{5}, " + //yearmade
            "'{6}', " + //latestplay
            "'{7}', " + //encode(description)
            "'{8}', " + //encode(genre)
            "'{9}', " + //encode(company)
            "'{10}'," + //visible
            "'{11}'," + //favourite
            "'{12}' ," + //encode(launchfile)
            "{13}, " + //emuprofile
            "'{14}'," + //infochecked 
            "'{15}'"; //hash

        const string UPDATE_STRING =
            "parentemu={1}, " +
            "title='{2}', " +
            "grade={3}, " +
            "playcount={4}, " +
            "yearmade={5}, " +
            "latestplay='{6}', " +
            "description='{7}', " +
            "genre='{8}', " +
            "company='{9}', " +
            "visible='{10}', " +
            "favourite='{11}', " +
            "LaunchFile='{12}', " +
            "emuprofile={13}, " +
            "infochecked='{14}', " +
            "hash='{15}' " +
            "WHERE path='{0}'";

        object[] DBParams
        {
            get
            {
                return new object[] 
                { 
                    DB.Encode(path),
                    parentEmulator.UID,
                    DB.Encode(title),
                    grade,
                    playcount,
                    yearmade,
                    latestplay,
                    DB.Encode(description),
                    DB.Encode(genre),
                    DB.Encode(company),
                    visible,
                    favourite,
                    DB.Encode(launchFile),
                    selectedProfile,
                    isInfoChecked,
                    hash
                };
            }
        }

        public static Game CreateGame(SQLite.NET.SQLiteResultSet.Row sqlRow)
        {
            return CreateGame(sqlRow, null);
        }

        public static Game CreateGame(SQLite.NET.SQLiteResultSet.Row sqlRow, Emulator parentEmulator)
        {
            if (sqlRow.fields.Count != 17)
            {
                Logger.LogError("Unable to create Game, invalid database row");
                return null;
            }

            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.InvariantCulture;
            
            if (parentEmulator == null)
                parentEmulator = DB.Instance.GetEmulator(int.Parse(sqlRow.fields[2], culture));

            if (parentEmulator == null)
                return null;

            Game game = new Game(DB.Decode(sqlRow.fields[1]), parentEmulator);
            //if (parentEmu == null)
            //item.ParentEmulator = getEmulator(DatabaseUtility.GetAsInt(result, rowIndex, 2));
            game.GameID = int.Parse(sqlRow.fields[0], culture);
            game.Title = DB.Decode(sqlRow.fields[3]);
            game.Grade = int.Parse(sqlRow.fields[4], culture);
            game.Playcount = int.Parse(sqlRow.fields[5], culture);
            game.Yearmade = int.Parse(sqlRow.fields[6], culture);
            game.Latestplay = DateTime.Parse(sqlRow.fields[7], culture);
            game.Description = DB.Decode(sqlRow.fields[8]);
            game.Genre = DB.Decode(sqlRow.fields[9]);
            game.Company = DB.Decode(sqlRow.fields[10]);
            game.Visible = Boolean.Parse(sqlRow.fields[11]);
            game.Favourite = Boolean.Parse(sqlRow.fields[12]);
            game.LaunchFile = DB.Decode(sqlRow.fields[13]);
            game.SelectedProfile = int.Parse(sqlRow.fields[14], culture);
            game.IsInfoChecked = Boolean.Parse(sqlRow.fields[15]);
            game.Hash = DB.Decode(sqlRow.fields[16]);
            return game;
        }

        public static string DBTableString
        {
            get
            {
                return "CREATE TABLE " + TABLE_NAME + "(" + TABLE_STRING + ")";
            }
        }

        public string GetDBInsertString()
        {
            return "INSERT INTO " + TABLE_NAME + " VALUES(" + string.Format(System.Globalization.CultureInfo.InvariantCulture, INSERT_STRING, DBParams) + ")";
        }

        public string GetDBUpdateString()
        {
            return "UPDATE " + TABLE_NAME + " SET " + string.Format(System.Globalization.CultureInfo.InvariantCulture, UPDATE_STRING, DBParams);
        }

        public void Save()
        {
            lock (DB.Instance.SyncRoot)
            {
                if (Exists())
                {
                    DB.Instance.Execute(GetDBUpdateString());
                }
                else
                {
                    SQLite.NET.SQLiteResultSet result = DB.Instance.ExecuteWithoutLock("SELECT MAX(gameid)+1 FROM {0}", TABLE_NAME);
                    if (result.Rows.Count > 0)
                        gameid = MediaPortal.Database.DatabaseUtility.GetAsInt(result, 0, 0);
                    else
                        gameid = 0;

                    DB.Instance.ExecuteWithoutLock(GetDBInsertString());
                }
            }
        }

        public void SaveGamePlayInfo()
        {
            DB.Instance.Execute("UPDATE {0} SET grade={1}, playcount={2}, latestplay='{3}', favourite='{4}', LaunchFile='{5}' WHERE path='{6}'",
                TABLE_NAME,
                grade, playcount, latestplay, favourite, DB.Encode(launchFile), DB.Encode(path)
                );
        }

        public void SaveInfoCheckedStatus()
        {
            DB.Instance.Execute("UPDATE {0} SET infochecked='{1}' WHERE path='{2}'", TABLE_NAME, isInfoChecked, DB.Encode(path));
        }

        public void Delete()
        {
            if (gameid < 0)
                return;

            lock (DB.Instance.SyncRoot)
            {
                DB.Instance.ExecuteWithoutLock("DELETE FROM {0} WHERE gameid={1}", TABLE_NAME, gameid);
                using (ThumbGroup thumbGroup = new ThumbGroup(this))
                {
                    try
                    {
                        if (System.IO.Directory.Exists(thumbGroup.ThumbPath))
                            System.IO.Directory.Delete(thumbGroup.ThumbPath, true);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("Error deleting {0} thumb directory - {1}", this.title, ex.Message);
                    }
                }
            }
        }

        public bool Exists()
        {
            return DB.Instance.Execute("SELECT 1 FROM {0} WHERE path='{1}'", TABLE_NAME, DB.Encode(path)).Rows.Count > 0;
        }

        #endregion
    }
}
